function call(destination, options, successor, damageControl, method) {
    if (typeof method == "undefined") {
        method = "get";
    }
    
    if (typeof damageControl == "undefined") {
        damageControl = successor;
    }
    
    method = String(method).toLowerCase();
    
    if (method.toLowerCase() == "delete") {
        method = "post";
        options['_method'] = "delete";
    }
    $.ajax({
        type: method,
        url: destination,
        data: options,
        success: successor,
        error: damageControl
    });
    
}

/**
 * @param destination {String}      (Optional) the destination. If it isn't given
 *                                  this will do reloading.
 */
function browse(destination, doQuietly) {
    getNumberOfSelectedItems();
    
    if (destination == null) {
        destination = lastAccessedLocation;
    }
    
    if (!doQuietly) {
        doQuietly = false;
        dialog.show("[opt:open-screen]" + dictionary.locale.message.event.listingInProgress);
    }
    
    $("#sstt").remove();
    
    call("storages/" + userID, {location: destination},
        function(xmlDoc) {
            $("#directories, #files").empty();
            var path = String($("info path", xmlDoc).text()).replace(/\/\/+/g, "/").split("/");
            lastAccessedLocation = $("info path", xmlDoc).text()
            $.cookie('lastAccessTo', lastAccessedLocation);
            
            $("#browser h2").html('<a class="location-path" path="">' + userID + '</a>');
            var cachedPath = '';
            $.each(path, function(index) {
                var directoryName = path[index];
                cachedPath += '/' + directoryName;
                cachedPath = cachedPath.replace(/^\//, '');
                $("#browser h2").append(
                    ' <img src="images/arrow-blue.png"/> '
                    + '<a class="location-path" path="' + cachedPath + '">'
                    + directoryName
                    + '</a>'
                );
            });
            var template = '';
            $("dir", xmlDoc).each(function(index) {
                template = $("#browser .prototype .directory").clone();
                $("#directories").append(template);
                $("#directories .directory:last .dn").attr("base", lastAccessedLocation);
                $("#directories .directory:last .dn").text($(this).text());
            });
            $("file", xmlDoc).each(function(index) {
                template = $("#browser .prototype .file").clone();
                var fileLocation = getCleanFilePath(userSiteBase + "/" + userID + "/" + lastAccessedLocation + "/" + $(this).text());
                $("#files").append(template);
                $("#files .file:last .fn").attr("base", lastAccessedLocation);
                $("#files .file:last .fn").text($(this).text());
                $("#files .file:last .ft").text($(this).attr("type"));
                $("#files .file:last .fs").text(getReadableFilesize($(this).attr("size")));
                $("#files .file:last .c-a-download").attr("title", "Click to download " + $(this).text());
                $("#files .file:last .c-a-download").attr("href", fileLocation);
                $("#files .file:last .c-a-download").attr("target", "_blank");
            });
            $("#display > div").hide();
            
            ui.items.synchronizeSelection();
            
            $("#browser").show();
            $("#browser-filter input").change();
            if (hasEnoughtSpace($("info usage", xmlDoc).text(), $("info quota", xmlDoc).text())) {
                if (!doQuietly) {
                    dialog.hide();
                }
            } else {
                if (!doQuietly) {
                    dialog.show(dictionary.locale.message.warning.aboutToExceedStorageLimit, true);
                }
            }
            if (!doQuietly) {
                if ($("#browser").hasClass("display-stock")) {
                    $("#a-stock").click();
                }
            }
        },
        function() {
            if (typeof(lastAccessedLocation) == "undefined") {
                lastAccessedLocation = '';
            }
            if (lastAccessedLocation != '') {
                browse(lastAccessedLocation.replace(/[^\/]+\/?$/, ''), doQuietly);
            } else {
                if (!doQuietly) {
                    dialog.show(dictionary.locale.message.error.failedToList, true);
                }
            }
        }
    );
}

function getNumberOfSelectedItems() {
    var numOfEntries = $("#browser-stock .entry").length;
    var listOfCommands = $("#a-reset-stock, #a-move, #a-delete");
    // Automatically show/hide the stock
    if (numOfEntries > 0) {
        $("#browser-suggest").html(
            dictionary.locale.label.browserSuggestWhatToDoWithSelectedItems(numOfEntries)
        );
        listOfCommands.slideDown(250);
    } else {
        $("#browser-suggest").html(
            dictionary.locale.label.browserSuggestWhatToDoFirst
        );
        listOfCommands.slideUp(250);
        $("#browser-stock").slideUp();
        $("#browser-forest").slideDown();
        $("#browser").removeClass("display-stock");
        $("#a-stock").removeClass("e-selected");
    }
    $("#a-stock span").html(numOfEntries);
    return numOfEntries;
}

function getReadableFilesize(size) {
    var units = ["B", "KB", "MB"];
    size = parseInt(size);
    i = 0;
    for(i = 0; i < units.length; ++i) {
        if (size < 1024) {
            break;
        }
        size /= 1024;
    }
    size *= 100;
    size = parseInt(size);
    size /= 100;
    return size + " " + units[i];
}

function buildDataString(dict) {
    var ret = [];
    $.each(dict, function(k, v) {
        ret.push(k + "=" + v);
    });
    return ret.join('&');
}

function windowHeight() {
    var ch = parseInt($(window).height());
    return ch < 400? 400: ch;
}

function windowWidth() {
    var cw = parseInt($(window).width());
    return cw < 920? 920: cw;
}

function getCleanFilePath(filePath) {
    return filePath.replace(/\/+/g, "/")
        .replace(/^\//, "")
        .replace(/\/$/, "")
        .replace(/^https:\//, "https://")
        .replace(/^http:\//, "http://")
        .replace(/^file:\//, "file:///")
        .replace(/^ftp:\//, "ftp://");
}

function isIE() {
    return $.support.opacity;
}

function hasEnoughtSpace(usage, quota) {
    userUsage = parseInt(usage)
    userQuota = parseInt(quota)
    
    var leftSpace = (100 - parseInt(userUsage / userQuota * 100));
    
    if (leftSpace < 4) {
        leftSpace = 3;
    }
    
    return leftSpace > 3;
}